package ua.edu.nuos.jeetraining2012.cms.util.template.material;

import ua.edu.nuos.jeetraining2012.cms.entity.CourseMaterialEntity;
import ua.edu.nuos.jeetraining2012.cms.service.exception.ServiceException;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;

/**
 * Template class for view.
 * <p/>
 * This class uses to show info about selected materials.
 *
 * @author Victor N. Ganichev victor.ganichev@gmail.com
 * @version 1.0 Date: 07.06.13 Time: 20:13
 * @since 1.0
 */
public class ViewTemplate extends DefaultMaterialTemplate {

    /**
     * Define material ID.
     */
    private Long materialId;

    /**
     * Define section title.
     */
    private String materialSectionTitle;

    /**
     * Define title.
     */
    private String materialTitle;

    /**
     * Define short description.
     */
    private String materialShortDescription;

    /**
     * Define text part of material.
     */
    private String materialText;

    /**
     * Define video URL.
     */
    private String materialVideoUrl;

    /**
     * Define presentation URL.
     */
    private String materialSlideUrl;

    /**
     * Define start date.
     */
    private Date materialStartDate;

    /**
     * Define end date.
     */
    private Date materialFinishDate;

    /**
     * Current accordion section.
     */
    private int currentCollapseNum;

    // Constructors.
    /**
     * Default constructor
     */
    public ViewTemplate() {
        super();
        logger.debug("ViewTemplate invocation.");
        templateName = "/view/material/view.ftl";
        logger.debug("redefine templateName to {}", templateName);
    }

    /**
     * Custom constructor with predefined material id.
     *
     * @param materialId        Long material ID.
     */
    public ViewTemplate(Long materialId) {
        this();
        logger.debug("ViewTemplate invocation with customised materialId {}", materialId);
        setMaterialId(materialId);
        initValues();
    }

    // Getters & Setters
    public Long getCourseId() {
        return courseId;
    }

    public void setCourseId(Long courseId) {
        this.courseId = courseId;
    }

    public Long getMaterialId() {
        return materialId;
    }

    public void setMaterialId(Long materialId) {
        this.materialId = materialId;
    }

    public String getMaterialSectionTitle() {
        return materialSectionTitle;
    }

    public void setMaterialSectionTitle(String materialSectionTitle) {
        this.materialSectionTitle = materialSectionTitle;
    }

    public String getMaterialTitle() {
        return materialTitle;
    }

    public void setMaterialTitle(String materialTitle) {
        this.materialTitle = materialTitle;
    }

    public String getMaterialShortDescription() {
        return materialShortDescription;
    }

    public void setMaterialShortDescription(String materialShortDescription) {
        this.materialShortDescription = materialShortDescription;
    }

    public String getMaterialText() {
        return materialText;
    }

    public void setMaterialText(String materialText) {
        this.materialText = materialText;
    }

    public String getMaterialVideoUrl() {
        return materialVideoUrl;
    }

    public void setMaterialVideoUrl(String materialVideoUrl) {
        this.materialVideoUrl = materialVideoUrl;
    }

    public String getMaterialSlideUrl() {
        return materialSlideUrl;
    }

    public void setMaterialSlideUrl(String materialSlideUrl) {
        this.materialSlideUrl = materialSlideUrl;
    }

    public Date getMaterialStartDate() {
        return materialStartDate;
    }

    public void setMaterialStartDate(Date materialStartDate) {
        this.materialStartDate = materialStartDate;
    }

    public Date getMaterialFinishDate() {
        return materialFinishDate;
    }

    public void setMaterialFinishDate(Date materialFinishDate) {
        this.materialFinishDate = materialFinishDate;
    }

    public int getCurrentCollapseNum() {
        return currentCollapseNum;
    }

    public void setCurrentCollapseNum(int currentCollapseNum) {
        this.currentCollapseNum = currentCollapseNum;
    }

    // Overrides

    /**
     * getMap.
     * <p/>
     * Override base getMap() method. Prepare all necessary vars for view template.
     *
     *
     * @return          HashMap with key & value pairs, to be shown in template.
     */
    @Override
    @SuppressWarnings("unchecked")
    public Map<String, Object> getMap() {
        logger.debug("getMap() - started.");

        String slideEncoded = materialSlideUrl;
        if (slideEncoded != null) {
            try {
                slideEncoded = URLEncoder.encode(materialSlideUrl, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                logger.debug("Can't encode URL; Error {}", e.getMessage());
            }
        }

        Map<String, Object> map = super.getMap();
        map.put("courseId", courseId);
        map.put("courseTitle", courseTitle);
        map.put("courseStartDate", courseStartDate);
        map.put("courseFinishDate", courseFinishDate);
        map.put("syllabusLink", syllabusLink);

        map.put("materials_titles", materialTitles);
        map.put("materialTitle", materialTitle);
        map.put("materialId", materialId);
        map.put("title", materialTitle);
        map.put("sectionTitle", materialSectionTitle);
        map.put("description", materialShortDescription);
        map.put("text", materialText);
        map.put("videoUrl", materialVideoUrl);
        map.put("slideUrl", slideEncoded);
        map.put("slideDownload", materialSlideUrl);
        map.put("startDate", materialStartDate);
        map.put("finishDate", materialFinishDate);
        map.put("isEnrolled", isEnrolled);

        map.put("hwList", hwList);

        map.put("currentCollapseNum", currentCollapseNum);

        Map<String, Object> i18nMap = (Map) map.get("i18n");
        map.put("i18n", getI18nMap(i18nMap));

        logger.debug("getMap() Map populated with values {}", map);

        logger.debug("getMap() - finished.");
        return map;
    }

    /**
     * initValues()
     * <p/>
     * Dummy method for invoke all necessary value population methods in one place.
     */
    private void initValues() {
        logger.debug("initValues() - started.");
        logger.debug("initValues() Trying to fetch values.");
        fetchMaterialInfo();
        if (courseId != null && courseId > 0) {
            logger.debug("Seams, that courseId is {}", courseId);
            fetchCourseTitles();
            fetchCourseInfo();
        }
        logger.debug("initValues() All possible values retrieved.");
        logger.debug("initValues() - finished.");
    }

    /**
     * fetchMaterialInfo()
     * <p/>
     * Fetch material data according to its ID.
     *
     */
    private void fetchMaterialInfo() {
        logger.debug("fetchMaterialInfo() - started.");
        CourseMaterialEntity materialInfo = null;

        try {
            logger.debug("fetchMaterialInfo() Trying to get material info with an ID {}", materialId);
            materialInfo = materialService.getMaterial(materialId);
            logger.debug("fetchMaterialInfo() Fetched info is {}", materialInfo);

        } catch (ServiceException e) {
            logger.error("fetchMaterialInfo() Can't retrieve material info. Got ServiceException with message: {}, \nTrace:\n{}",
                    e.getMessage(), Arrays.deepToString(e.getStackTrace()));
            logger.debug("fetchMaterialInfo()  caught ServiceException. Creating default values.");
        }

        appendMaterialToTemplate(materialInfo);

        logger.debug("fetchMaterialInfo() - finished");
    }

    /**
     * appendMaterialToTemplate()
     * <p/>
     * Fill all possible variables that uses in view template.
     *
     * @param materialInfo      CourseMaterialEntity instance with fetched values.
     */
    private void appendMaterialToTemplate(CourseMaterialEntity materialInfo) {
        logger.debug("appendMaterialToTemplate() - started.");
        logger.debug("appendMaterialToTemplate() Sent materialInfo is {}", materialInfo.toString());

        courseId = materialInfo.getCourse().getId();
        courseDescription = materialInfo.getCourse().getDescription();
        courseTitle = materialInfo.getCourse().getTitle();
        courseStartDate = materialInfo.getCourse().getStartDate();
        courseFinishDate = materialInfo.getCourse().getFinishDate();
        syllabusLink = materialInfo.getCourse().getSyllabusLink();

        materialTitle = materialInfo.getTitle();
        materialSectionTitle = materialInfo.getSectionTitle();
        materialShortDescription = materialInfo.getShortDescription();
        materialText = materialInfo.getText();
        materialVideoUrl = materialInfo.getVideoURL();
        materialSlideUrl = materialInfo.getSlideURL();
        materialStartDate = materialInfo.getStartDate();
        materialFinishDate = materialInfo.getDueDate();

        logger.debug("appendMaterialToTemplate() - finished.");
    }


}
